package com.nowcoder.topic.dp.hard;

/**
 * NC178 打家劫舍(三)
 * @author d3y1
 */
public class NC178{
    /**
     * 代码中的类名、方法名、参数名已经指定，请勿修改，直接返回方法规定的值即可
     *
     *
     * @param root TreeNode类
     * @return int整型
     */
    public int rob (TreeNode root) {
        return solution1(root);
//        return solution2(root);
    }

    /**
     * 动态规划
     *
     * 自底向上
     *
     * left[0]  表示不偷左子节点时可获得的最多金额
     * left[1]  表示偷窃左子节点时可获得的最多金额
     * right[0] 表示不偷右子节点时可获得的最多金额
     * right[1] 表示偷窃右子节点时可获得的最多金额
     * curr[0]  表示不偷当前节点时可获得的最多金额
     * curr[1]  表示偷窃当前节点时可获得的最多金额
     *
     * curr[0] = Math.max(left[0], left[1]) + Math.max(right[0], right[1])
     * curr[1] = root.val + left[0] + right[0]
     *
     * @param root
     * @return
     */
    private int solution1(TreeNode root){
        int[] result = new int[2];

        result = postOrder(root);

        return Math.max(result[0], result[1]);
    }

    /**
     * 后序遍历
     * @param root
     * @return
     */
    private int[] postOrder(TreeNode root){
        if(root == null){
            return new int[2];
        }

        int[] left = postOrder(root.left);
        int[] right = postOrder(root.right);

        int[] curr = new int[2];
        // 不偷 当前节点
        // curr[0] = Math.max(left[1]+right[1], Math.max(left[0]+right[0], Math.max(left[1]+right[0], left[0]+right[1])));
        curr[0] = Math.max(left[0], left[1]) + Math.max(right[0], right[1]);
        // 偷窃 当前节点 左右子节点都不能偷
        curr[1] = root.val + left[0] + right[0];

        return curr;
    }

    /**
     * 递归: 遍历解空间: 超时
     * @param root
     * @return
     */
    private int solution2(TreeNode root){
        int result = preOrder(root);

        return result;
    }

    /**
     * 前序遍历
     * @param root
     * @return
     */
    private int preOrder(TreeNode root){
        if(root == null){
            return 0;
        }

        int[] curr = new int[2];
        // 偷窃 当前节点
        curr[1] = root.val;
        if(root.left != null){
            curr[1] += preOrder(root.left.left) + preOrder(root.left.right);
        }
        if(root.right != null){
            curr[1] += preOrder(root.right.left) + preOrder(root.right.right);
        }

        // 不偷 当前节点
        curr[0] = preOrder(root.left) + preOrder(root.right);

        return Math.max(curr[0], curr[1]);
    }

    private class TreeNode {
        int val = 0;
        TreeNode left = null;
        TreeNode right = null;

        public TreeNode(int val) {
            this.val = val;
        }
    }
}